// Shared variables - available in all effects
// These don't need to be set manually
shared float2 PixelSize;
shared float4x4 InvViewProj;
shared float3 CameraPosition;

float focalDistance;
float focalLength;

// Samplers
texture inputTexture;
sampler inputSampler = sampler_state
{
	texture = <inputTexture>;
	magfilter = LINEAR;
	minfilter = LINEAR;
	AddressU = clamp;
	AddressV = clamp;
};
texture depthTexture;
sampler depthSampler = sampler_state
{
	texture = <depthTexture>;
	magfilter = LINEAR;
	minfilter = LINEAR;
	AddressU = clamp;
	AddressV = clamp;
};
texture blurTexture;
sampler blurSampler = sampler_state
{
	texture = <blurTexture>; 
	magfilter = LINEAR;
	minfilter = LINEAR;
	AddressU = clamp;
	AddressV = clamp;
};


struct VS_INPUT
{
	float4 Position		: POSITION;
	float2 TexCoords	: TEXCOORD0;
};

struct VS_OUTPUT
{
	float4 Position : POSITION;
	float2 TexCoords : TEXCOORD0;
};

VS_OUTPUT VertexShaderFunction(VS_INPUT input)
{
	VS_OUTPUT output;
	output.Position = input.Position;
	output.TexCoords = input.TexCoords;
	return output;
}


// Depth of field shader - combines blur with color based on DOF params
float4 DofShader(VS_OUTPUT output) : COLOR
{
	// Get the depth
	FLOAT depth = tex2D(depthSampler, output.TexCoords).r;

	// Clip if depth is out of range
	clip(depth * 2.0f - 1.0f);

	// Get the color and blur color
	float4 baseColor = tex2D(inputSampler, output.TexCoords);
	float4 blurColor = tex2D(blurSampler, output.TexCoords);

	// Get world position
	float4 screenPos = float4(
		output.TexCoords.x * 2.0f - 1.0f,
		(1.0f - output.TexCoords.y) * 2.0f - 1.0f,
		depth,
		1.0f);
	float4 worldPos = mul(screenPos, InvViewProj);
	
	// Calculate focal amount
	FLOAT distanceFromFocus = distance(
		focalDistance,
		distance((worldPos.xyz / worldPos.w), CameraPosition)
		);
	FLOAT focalValue = smoothstep(0.0f, focalLength, distanceFromFocus);
	
	// Get color
	float4 returnColor = lerp(baseColor, blurColor, focalValue);
	
	// Return the color
	return returnColor;
}

technique DepthOfField
{
	pass Pass0
	{
		vertexShader = compile vs_2_0 VertexShaderFunction();
		pixelShader = compile ps_2_0 DofShader();
	}
}